﻿using System;
using System.IO;
using System.Net;
using System.Text;

namespace Toybox.NicoSharp.Utilities
{
	/// <summary>
	/// NicoNico用のWebClient
	/// </summary>
	public class NicoWebClient : WebClient
	{

		#region [Static]

		/// <summary>
		/// ユーザーエージェント
		/// </summary>
		public static string UserAgent { get; set; }

		/// <summary>
		/// HTTPアクセス (GET)
		/// </summary>
		/// <param name="url"></param>
		/// <param name="cookies"></param>
		/// <param name="referer"></param>
		/// <returns></returns>
		/// <exception cref="System.ArgumentNullException"></exception>
		/// <exception cref="System.Net.WebException"></exception>
		/// <exception cref="System.NotSupportedException"></exception>
		/// <exception cref="System.OutOfMemoryException"></exception>
		/// <exception cref="System.IO.IOException"></exception>
		public static string Get(string url, CookieCollection cookies = null, string referer = null)
		{
			using (var wc = new NicoWebClient())
			{
				if (cookies != null)
					wc.CookieContainer.Add(cookies);
				wc.Encoding = Encoding.UTF8;
				wc.Referer = referer;

				try
				{
					return wc.DownloadString(url);
				}
				catch (WebException we)
				{
					if (we.Status == WebExceptionStatus.ProtocolError)
						return new StreamReader(we.Response.GetResponseStream(), Encoding.UTF8).ReadToEnd();
					throw;
				}
				catch
				{
					throw;
				}
			}
		}

		/// <summary>
		/// HTTPアクセス (POST)
		/// </summary>
		/// <param name="url"></param>
		/// <param name="data"></param>
		/// <param name="cookies"></param>
		/// <param name="referer"></param>
		/// <returns></returns>
		/// <exception cref="System.ArgumentNullException"></exception>
		/// <exception cref="System.ArgumentException"></exception>
		/// <exception cref="System.ArgumentOutOfRangeException"></exception>
		/// <exception cref="System.Net.WebException"></exception>
		public static string Post(string url, string data, CookieCollection cookies = null, string referer = null)
		{
			using (var wc = new NicoWebClient())
			{
				if (cookies != null)
					wc.CookieContainer.Add(cookies);
				
				wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
				wc.Encoding = Encoding.UTF8;
				wc.Referer = referer;

				return wc.UploadString(url, data);
			}
		}

		/// <summary>
		/// リダイレクトURL取得
		/// </summary>
		/// <param name="url"></param>
		/// <param name="cookies"></param>
		/// <param name="referer"></param>
		/// <returns></returns>
		/// <exception cref="System.NotSupportedException"></exception>
		/// <exception cref="System.ArgumentNullException"></exception>
		/// <exception cref="System.Security.SecurityException"></exception>
		/// <exception cref="System.System.UriFormatException"></exception>
		/// <exception cref="System.InvalidOperationException"></exception>
		/// <exception cref="System.Net.ProtocolViolationException"></exception>
		/// <exception cref="System.Net.WebException"></exception>
		/// <exception cref="System.ArgumentNullException"></exception>
		public static string GetRedirectUrl(string url, CookieCollection cookies = null, string referer = null)
		{
			HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
			request.AllowAutoRedirect = false;
			if (cookies != null)
			{
				request.CookieContainer = new CookieContainer();
				request.CookieContainer.Add(cookies);
			}
			if (referer != null)
			{
				request.Referer = referer;
			}

			WebResponse response = request.GetResponse();
			string result = response.Headers.Get("Location");
			return result == null ? response.ResponseUri.ToString() : result;
		}

		#endregion [Static]


		#region Public Members

		/// <summary>
		/// CookieContainer
		/// </summary>
		public CookieContainer CookieContainer
		{
			get
			{
				if (_cookieContainer == null)
					_cookieContainer = new CookieContainer();

				return _cookieContainer;
			}
			set { _cookieContainer = value; }
		}
		private CookieContainer _cookieContainer;

		/// <summary>
		/// Referer
		/// </summary>
		public string Referer { get; set; }

		#endregion Public Members

		#region Protected Members

		/// <summary>
		/// WebRequestの上書き
		/// </summary>
		/// <param name="uri"></param>
		/// <returns></returns>
		protected override WebRequest GetWebRequest(Uri uri)
		{
			var request = base.GetWebRequest(uri);

			if (request is HttpWebRequest)
			{
				var req = request as HttpWebRequest;

				req.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
				req.Headers["Accept-Language"] = "ja,en-us;q=0.7,en;q=0.3";
				req.Headers["Accept-Charset"] = "Shift_JIS,utf-8;q=0.7,*;q=0.7";
				req.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;

				req.CookieContainer = this.CookieContainer;
				req.UserAgent = UserAgent;
				req.Referer = this.Referer;
			}

			return request;
		}

		#endregion Protected Members

	}
}